package models

import (
	"encoding/json"
	"fmt"
	"gitee.com/tsingeye/FreeEhome/config"
	"gitee.com/tsingeye/FreeEhome/tools"
	"gitee.com/tsingeye/FreeEhome/tools/logs"
	"gitee.com/tsingeye/FreeEhome/tools/redisDB"
	"gitee.com/tsingeye/FreeEhome/tools/sqlDB"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/mem"
	"github.com/shirou/gopsutil/net"
	"strings"
	"time"
)

type loginRequestBody struct {
	UserID   string `json:"userID"`   //用户ID
	Password string `json:"password"` //用户密码
}

//登录
func Login(requestBody []byte, remoteAddr string) (replyData map[string]interface{}, token string) {
	var loginData loginRequestBody
	if err := json.Unmarshal(requestBody, &loginData); err != nil {
		logs.BeeLogger.Error("SystemController.Login() ---> remoteAddr=%s, requestBody=%s, json.Unmarshal() error:%s", remoteAddr, requestBody, err)

		replyData = map[string]interface{}{
			"errCode": config.EHomeClientBadRequest,
			"errMsg":  config.HTTPCodeMap[config.EHomeClientBadRequest],
		}
		return
	}

	if err := sqlDB.First(&sqlDB.UserTable{}, "userID = ? AND password = ?", loginData.UserID, strings.ToLower(loginData.Password)); err != nil {
		//查询用户是否存在，查询出错默认是该用户不存在
		logs.BeeLogger.Error("SystemController.Login() ---> remoteAddr=%s, requestBody=%s, error:%s, user not found, login failed!!!", remoteAddr, requestBody, err)

		replyData = map[string]interface{}{
			"errCode": config.EHomeUserNotFound,
			"errMsg":  config.HTTPCodeMap[config.EHomeUserNotFound],
		}
		return
	}

	//token生成
	token = tools.GetUUID()
	if err := redisDB.SetEX(token, token, config.TokenExpiresAt); err != nil {
		logs.BeeLogger.Error("SystemController.Login() ---> remoteAddr=%s, redisDB.SetEX() key=%s,value=%s, error:%s", remoteAddr, token, token, err)

		replyData = map[string]interface{}{
			"errCode": config.EHomeServerError,
			"errMsg":  config.HTTPCodeMap[config.EHomeServerError],
		}
		return
	}

	replyData = map[string]interface{}{
		"errCode": config.EHomeSuccessOK,
		"errMsg":  config.HTTPCodeMap[config.EHomeSuccessOK],
	}

	return replyData, token
}

//登出，从redis数据库删除该token
func Logout(token, remoteAddr string) (replyData map[string]interface{}) {
	logs.BeeLogger.Emergency("SystemController.Logout() ---> remoteAddr=%s, token=%s, logout successfully!!!", remoteAddr, token)

	//删除token
	redisDB.Del(token)

	replyData = map[string]interface{}{
		"errCode": config.EHomeSuccessOK,
		"errMsg":  config.HTTPCodeMap[config.EHomeSuccessOK],
	}
	return
}

//获取系统信息：CPU、网络、内存等信息
func SystemInfo() (replyData map[string]interface{}) {
	replyData = map[string]interface{}{
		"errCode": config.EHomeServerError,
		"errMsg":  config.HTTPCodeMap[config.EHomeServerError],
	}

	//CPU信息
	percent, err := cpu.Percent(time.Second, false)
	if err != nil {
		logs.BeeLogger.Error("cpu.Percent error: %s", err)
		return
	}

	//内存信息
	memory, err := mem.VirtualMemory()
	if err != nil {
		logs.BeeLogger.Error("mem.VirtualMemory error: %s", err)
		return
	}

	//网络信息
	beforeIO, err := net.IOCounters(false)
	if err != nil {
		logs.BeeLogger.Error("net.IOCounters error: %s", err)
		return
	}
	time.Sleep(1 * time.Second)
	afterIO, err := net.IOCounters(false)
	if err != nil {
		logs.BeeLogger.Error("net.IOCounters error: %s", err)
		return
	}

	//上传速度
	uploadSpeed := (afterIO[0].BytesSent - beforeIO[0].BytesSent) / 1024
	//fmt.Println("打印上传速度：", afterIO[0].BytesSent - beforeIO[0].BytesSent)
	//下载速度
	downloadSpeed := (afterIO[0].BytesRecv - beforeIO[0].BytesRecv) / 1024
	//fmt.Println("打印下载速度：", afterIO[0].BytesRecv - beforeIO[0].BytesRecv)

	replyData = map[string]interface{}{
		"errCode":        config.EHomeSuccessOK,
		"errMsg":         config.HTTPCodeMap[config.EHomeSuccessOK],
		"cpuUsedPercent": fmt.Sprintf("%d%s", int(percent[0]), "%"),
		"virtualMemory": map[string]interface{}{
			"total":       fmt.Sprintf("%dMB", memory.Total/1024/1024),
			"available":   fmt.Sprintf("%dMB", memory.Available/1024/1024),
			"used":        fmt.Sprintf("%dMB", memory.Used/1024/1024),
			"usedPercent": fmt.Sprintf("%d%s", int(memory.UsedPercent), "%"),
		},
		"network": map[string]interface{}{
			"uploadSpeed":   fmt.Sprintf("%dKB/s", uploadSpeed),
			"downloadSpeed": fmt.Sprintf("%dKB/s", downloadSpeed),
		},
		"deviceInfo": map[string]interface{}{
			"totalCount":  sqlDB.Count(&sqlDB.DeviceTable{}, ""),
			"onlineCount": sqlDB.Count(&sqlDB.DeviceTable{}, "status = ?", "ON"),
		},
		"channelInfo": map[string]interface{}{
			"totalCount":  sqlDB.Count(&sqlDB.ChannelTable{}, ""),
			"onlineCount": sqlDB.Count(&sqlDB.ChannelTable{}, "status = ?", "ON"),
		},
	}
	return
}
